<template>
  <div class="confusion-matrix-container">
    <div class="matrix-header">
      <h3>混淆矩阵</h3>
      <div class="time-selector" v-if="matrixData.length > 1">
        <label>时间点选择：</label>
        <select v-model="selectedTimeIndex" @change="updateMatrix">
          <option v-for="(item, index) in matrixData" :key="index" :value="index">
            时间点 {{ index + 1 }}
          </option>
        </select>
      </div>
    </div>

    <div class="matrix-wrapper" v-if="parsedMatrix">
      <!-- 混淆矩阵表格 -->
      <div class="matrix-table">
        <table>
          <thead>
            <tr>
              <th rowspan="2" class="corner-cell">实际\预测</th>
              <th colspan="2">模型预测</th>
              <th rowspan="2" class="total-header">总数</th>
            </tr>
            <tr>
              <th class="positive-header">正例</th>
              <th class="negative-header">负例</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td class="row-header positive-header">实际正例</td>
              <td class="tp-cell" :title="`真正例: ${parsedMatrix[0][0]}`">
                <div class="cell-label">TP</div>
                <div class="cell-value">{{ parsedMatrix[0][0] }}</div>
              </td>
              <td class="fn-cell" :title="`假负例: ${parsedMatrix[0][1]}`">
                <div class="cell-label">FN</div>
                <div class="cell-value">{{ parsedMatrix[0][1] }}</div>
              </td>
              <td class="total-cell">{{ totalTpFn }}</td>
            </tr>
            <tr>
              <td class="row-header negative-header">实际负例</td>
              <td class="fp-cell" :title="`假正例: ${parsedMatrix[1][0]}`">
                <div class="cell-label">FP</div>
                <div class="cell-value">{{ parsedMatrix[1][0] }}</div>
              </td>
              <td class="tn-cell" :title="`真负例: ${parsedMatrix[1][1]}`">
                <div class="cell-label">TN</div>
                <div class="cell-value">{{ parsedMatrix[1][1] }}</div>
              </td>
              <td class="total-cell">{{ totalFpTn }}</td>
            </tr>
            <tr class="total-row">
              <td class="total-header">总数</td>
              <td class="total-cell">{{ totalTpFp }}</td>
              <td class="total-cell">{{ totalFnTn }}</td>
              <td class="grand-total-cell">{{ grandTotal }}</td>
            </tr>
          </tbody>
        </table>
      </div>

      <!-- ECharts 柱状图 -->
      <div class="charts-section">
        <div class="chart-container">
          <div id="matrixBarChart" style="width: 100%; height: 350px;"></div>
        </div>
        <div class="chart-container">
          <div id="metricsBarChart" style="width: 100%; height: 350px;"></div>
        </div>
      </div>

      <!-- 性能指标数值 -->
      <div class="metrics-summary">
        <div class="metric-item">
          <span class="metric-label">准确率 (Accuracy):</span>
          <span class="metric-value">{{ (accuracy * 100).toFixed(2) }}%</span>
        </div>
        <div class="metric-item">
          <span class="metric-label">精确率 (Precision):</span>
          <span class="metric-value">{{ (precision * 100).toFixed(2) }}%</span>
        </div>
        <div class="metric-item">
          <span class="metric-label">召回率 (Recall):</span>
          <span class="metric-value">{{ (recall * 100).toFixed(2) }}%</span>
        </div>
        <div class="metric-item">
          <span class="metric-label">F1分数 (F1-Score):</span>
          <span class="metric-value">{{ f1Score.toFixed(4) }}</span>
        </div>
      </div>
    </div>

    <div v-else class="no-data">
      <p>暂无混淆矩阵数据</p>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts'

export default {
  name: 'ConfusionMatrix',
  props: {
    confusionMatrix: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      selectedTimeIndex: 0,
      matrixBarChart: null,
      metricsBarChart: null
    }
  },
  computed: {
    matrixData() {
      return this.confusionMatrix.filter(item => item !== null && item !== undefined)
    },

    parsedMatrix() {
      if (!this.matrixData.length || this.selectedTimeIndex >= this.matrixData.length) {
        return null
      }

      try {
        const matrixString = this.matrixData[this.selectedTimeIndex]
        if (typeof matrixString === 'string') {
          return JSON.parse(matrixString)
        }
        return matrixString
      } catch (error) {
        console.error('解析混淆矩阵数据失败:', error)
        return null
      }
    },

    // 计算总数
    totalTpFn() {
      if (!this.parsedMatrix) return 0
      return this.parsedMatrix[0][0] + this.parsedMatrix[0][1]
    },

    totalFpTn() {
      if (!this.parsedMatrix) return 0
      return this.parsedMatrix[1][0] + this.parsedMatrix[1][1]
    },

    totalTpFp() {
      if (!this.parsedMatrix) return 0
      return this.parsedMatrix[0][0] + this.parsedMatrix[1][0]
    },

    totalFnTn() {
      if (!this.parsedMatrix) return 0
      return this.parsedMatrix[0][1] + this.parsedMatrix[1][1]
    },

    grandTotal() {
      if (!this.parsedMatrix) return 0
      return this.parsedMatrix[0][0] + this.parsedMatrix[0][1] +
             this.parsedMatrix[1][0] + this.parsedMatrix[1][1]
    },

    // 性能指标计算
    accuracy() {
      if (!this.parsedMatrix || this.grandTotal === 0) return 0
      const tp = this.parsedMatrix[0][0]
      const tn = this.parsedMatrix[1][1]
      return (tp + tn) / this.grandTotal
    },

    precision() {
      if (!this.parsedMatrix) return 0
      const tp = this.parsedMatrix[0][0]
      const fp = this.parsedMatrix[1][0]
      return tp + fp === 0 ? 0 : tp / (tp + fp)
    },

    recall() {
      if (!this.parsedMatrix) return 0
      const tp = this.parsedMatrix[0][0]
      const fn = this.parsedMatrix[0][1]
      return tp + fn === 0 ? 0 : tp / (tp + fn)
    },

    f1Score() {
      if (this.precision + this.recall === 0) return 0
      return 2 * (this.precision * this.recall) / (this.precision + this.recall)
    }
  },

  watch: {
    confusionMatrix: {
      handler() {
        this.selectedTimeIndex = 0
        this.$nextTick(() => {
          this.updateCharts()
        })
      },
      immediate: true
    },

    parsedMatrix() {
      this.$nextTick(() => {
        this.updateCharts()
      })
    }
  },

  mounted() {
    this.initCharts()
    this.updateCharts()
  },

  beforeDestroy() {
    if (this.matrixBarChart) {
      this.matrixBarChart.dispose()
    }
    if (this.metricsBarChart) {
      this.metricsBarChart.dispose()
    }
  },

  methods: {
    updateMatrix() {
      this.$nextTick(() => {
        this.updateCharts()
      })
    },

    initCharts() {
      // 初始化混淆矩阵柱状图
      const matrixElement = document.getElementById('matrixBarChart')
      if (matrixElement) {
        this.matrixBarChart = echarts.init(matrixElement)
      }

      // 初始化性能指标柱状图
      const metricsElement = document.getElementById('metricsBarChart')
      if (metricsElement) {
        this.metricsBarChart = echarts.init(metricsElement)
      }
    },

    updateCharts() {
      if (!this.parsedMatrix) return

      this.updateMatrixBarChart()
      this.updateMetricsBarChart()
    },

    updateMatrixBarChart() {
      if (!this.matrixBarChart || !this.parsedMatrix) return

      const option = {
        title: {
          text: '混淆矩阵数值分布',
          left: 'center',
          textStyle: {
            fontSize: 16,
            fontWeight: 'bold'
          }
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          },
          formatter: function(params) {
            const data = params[0]
            const descriptions = {
              'TP': '真正例 - 正确预测为正例',
              'FN': '假负例 - 错误预测为负例',
              'FP': '假正例 - 错误预测为正例',
              'TN': '真负例 - 正确预测为负例'
            }
            return `${data.name}: ${data.value}<br/>${descriptions[data.name]}`
          }
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: ['TP (真正例)', 'FN (假负例)', 'FP (假正例)', 'TN (真负例)'],
          axisLabel: {
            interval: 0,
            rotate: 0,
            fontSize: 12
          }
        },
        yAxis: {
          type: 'value',
          name: '数量',
          nameTextStyle: {
            fontSize: 12
          }
        },
        series: [{
          type: 'bar',
          data: [
            {
              name: 'TP',
              value: this.parsedMatrix[0][0],
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: '#83bff6' },
                  { offset: 0.5, color: '#188df0' },
                  { offset: 1, color: '#188df0' }
                ])
              }
            },
            {
              name: 'FN',
              value: this.parsedMatrix[0][1],
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: '#ffd666' },
                  { offset: 0.5, color: '#faad14' },
                  { offset: 1, color: '#faad14' }
                ])
              }
            },
            {
              name: 'FP',
              value: this.parsedMatrix[1][0],
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: '#ff9c6e' },
                  { offset: 0.5, color: '#ff4d4f' },
                  { offset: 1, color: '#ff4d4f' }
                ])
              }
            },
            {
              name: 'TN',
              value: this.parsedMatrix[1][1],
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: '#95de64' },
                  { offset: 0.5, color: '#52c41a' },
                  { offset: 1, color: '#52c41a' }
                ])
              }
            }
          ],
          label: {
            show: true,
            position: 'top',
            fontSize: 12,
            fontWeight: 'bold'
          },
          barWidth: '60%'
        }]
      }

      this.matrixBarChart.setOption(option)
    },

    updateMetricsBarChart() {
      if (!this.metricsBarChart || !this.parsedMatrix) return

      const option = {
        title: {
          text: '模型性能指标',
          left: 'center',
          textStyle: {
            fontSize: 16,
            fontWeight: 'bold'
          }
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          },
          formatter: function(params) {
            const data = params[0]
            const descriptions = {
              '准确率': '正确预测的样本占总样本的比例',
              '精确率': '预测为正例中实际为正例的比例',
              '召回率': '实际正例中被正确预测的比例',
              'F1分数': '精确率和召回率的调和平均数'
            }
            return `${data.name}: ${(data.value * 100).toFixed(2)}%<br/>${descriptions[data.name]}`
          }
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: ['准确率', '精确率', '召回率', 'F1分数'],
          axisLabel: {
            interval: 0,
            fontSize: 12
          }
        },
        yAxis: {
          type: 'value',
          name: '数值',
          nameTextStyle: {
            fontSize: 12
          },
          max: 1,
          axisLabel: {
            formatter: function(value) {
              return (value * 100).toFixed(0) + '%'
            }
          }
        },
        series: [{
          type: 'bar',
          data: [
            {
              value: this.accuracy,
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: '#87d068' },
                  { offset: 1, color: '#52c41a' }
                ])
              }
            },
            {
              value: this.precision,
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: '#69c0ff' },
                  { offset: 1, color: '#1890ff' }
                ])
              }
            },
            {
              value: this.recall,
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: '#ffbb96' },
                  { offset: 1, color: '#fa8c16' }
                ])
              }
            },
            {
              value: this.f1Score,
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: '#b37feb' },
                  { offset: 1, color: '#722ed1' }
                ])
              }
            }
          ],
          label: {
            show: true,
            position: 'top',
            fontSize: 12,
            fontWeight: 'bold',
            formatter: function(params) {
              return (params.value * 100).toFixed(1) + '%'
            }
          },
          barWidth: '60%'
        }]
      }

      this.metricsBarChart.setOption(option)
    }
  }
}
</script>

<style scoped>
.confusion-matrix-container {
  padding: 20px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.matrix-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 1px solid #e8e8e8;
}

.matrix-header h3 {
  margin: 0;
  color: #333;
  font-size: 18px;
}

.time-selector {
  display: flex;
  align-items: center;
  gap: 8px;
}

.time-selector label {
  font-size: 14px;
  color: #666;
}

.time-selector select {
  padding: 4px 8px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  font-size: 14px;
}

.matrix-wrapper {
  display: flex;
  flex-direction: column;
  gap: 30px;
}

.matrix-table {
  overflow-x: auto;
}

.matrix-table table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 auto;
  max-width: 600px;
}

.matrix-table th,
.matrix-table td {
  border: 1px solid #e8e8e8;
  padding: 12px;
  text-align: center;
  font-weight: 500;
}

.corner-cell {
  background: #f5f5f5;
  font-weight: bold;
  color: #333;
}

.positive-header {
  background: #e6f7ff;
  color: #1890ff;
  font-weight: bold;
}

.negative-header {
  background: #fff2e8;
  color: #fa8c16;
  font-weight: bold;
}

.total-header {
  background: #f6ffed;
  color: #52c41a;
  font-weight: bold;
}

.row-header {
  font-weight: bold;
  min-width: 80px;
}

.tp-cell {
  background: #f6ffed;
  color: #52c41a;
}

.fn-cell {
  background: #fff7e6;
  color: #faad14;
}

.fp-cell {
  background: #fff1f0;
  color: #ff4d4f;
}

.tn-cell {
  background: #e6f7ff;
  color: #1890ff;
}

.total-cell {
  background: #f0f0f0;
  font-weight: bold;
  color: #333;
}

.grand-total-cell {
  background: #e6f7ff;
  font-weight: bold;
  color: #1890ff;
  font-size: 16px;
}

.total-row {
  border-top: 2px solid #d9d9d9;
}

.cell-label {
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 4px;
}

.cell-value {
  font-size: 16px;
  font-weight: bold;
}

.charts-section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin: 20px 0;
}

.chart-container {
  border: 1px solid #e8e8e8;
  border-radius: 8px;
  padding: 10px;
  background: #fafafa;
}

.metrics-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 15px;
  margin-top: 20px;
  padding: 20px;
  background: #fafafa;
  border-radius: 8px;
}

.metric-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  background: #fff;
  border-radius: 6px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.metric-label {
  font-weight: 500;
  color: #666;
}

.metric-value {
  font-weight: bold;
  color: #1890ff;
  font-size: 16px;
}

.no-data {
  text-align: center;
  padding: 40px;
  color: #999;
}

@media (max-width: 768px) {
  .matrix-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }

  .charts-section {
    grid-template-columns: 1fr;
  }

  .metrics-summary {
    grid-template-columns: 1fr;
  }

  .matrix-table {
    font-size: 12px;
  }

  .matrix-table th,
  .matrix-table td {
    padding: 8px 4px;
  }
}
</style>
